using System;
using NFreeMarker.Template;

namespace NFreeMarker.Ext.Beans
{
    /**
     * @author Attila Szegedi
     * @version $Id: HashAdapter.java,v 1.2 2005/06/12 19:03:04 szegedia Exp $
     */
    public class HashAdapter : ITemplateModelAdapter // TODO: AbstractMap
    {
        private readonly BeansWrapper _wrapper;
        private readonly ITemplateHashModel _model;
        //private Set _entrySet;
        
        internal HashAdapter(ITemplateHashModel model, BeansWrapper wrapper)
        {
            _model = model;
            _wrapper = wrapper;
        }
        
        public ITemplateModel GetTemplateModel()
        {
            return _model;
        }
        
        public bool IsEmpty()
        {
            try
            {
                return _model.IsEmpty();
            }
            catch (TemplateModelException e)
            {
                //throw new UndeclaredThrowableException(e);
                throw new NotImplementedException();
            }
        }
        
        public object Get(object key)
        {
            try
            {
                return _wrapper.Unwrap(_model.Get(Convert.ToString(key)));
            }
            catch(TemplateModelException e)
            {
                //throw new UndeclaredThrowableException(e);
                throw new NotImplementedException();
            }
        }

        public bool ContainsKey(object key)
        {
            // A quick check that doesn't require TemplateHashModelEx 
            if (Get(key) != null)
            {
                return true;
            }
            //return base.ContainsKey(key);
            throw new NotImplementedException();
        }
        
        //public Set EntrySet()
        //{
        //    if (_entrySet != null)
        //    {
        //        return _entrySet;
        //    }
        //    return _entrySet = new AbstractSet()
        //    {
        //        public Iterator iterator() {
        //            final TemplateModelIterator i;
        //            try {
        //                 i = getModelEx().keys().iterator();
        //            }
        //            catch(TemplateModelException e) {
        //                throw new UndeclaredThrowableException(e);
        //            }
        //            return new Iterator() {
        //                public boolean hasNext() {
        //                    try {
        //                        return i.hasNext();
        //                    }
        //                    catch(TemplateModelException e) {
        //                        throw new UndeclaredThrowableException(e);
        //                    }
        //                }
                        
        //                public Object next() {
        //                    final Object key;
        //                    try {
        //                        key = wrapper.unwrap(i.next());
        //                    }
        //                    catch(TemplateModelException e) {
        //                        throw new UndeclaredThrowableException(e);
        //                    }
        //                    return new Map.Entry() {
        //                        public Object getKey() {
        //                            return key;
        //                        }
                                
        //                        public Object getValue() {
        //                            return get(key);
        //                        }
                                
        //                        public Object setValue(Object value) {
        //                            throw new UnsupportedOperationException();
        //                        }
                                
        //                        public boolean equals(Object o) {
        //                            if (!(o instanceof Map.Entry))
        //                                return false;
        //                            Map.Entry e = (Map.Entry)o;
        //                            Object k1 = getKey();
        //                            Object k2 = e.getKey();
        //                            if (k1 == k2 || (k1 != null && k1.equals(k2))) {
        //                                Object v1 = getValue();
        //                                Object v2 = e.getValue();
        //                                if (v1 == v2 || (v1 != null && v1.equals(v2))) 
        //                                    return true;
        //                            }
        //                            return false;
        //                        }
                            
        //                        public int hashCode() {
        //                            Object value = getValue();
        //                            return (key==null ? 0 : key.hashCode()) ^
        //                                   (value==null ? 0 : value.hashCode());
        //                        }
        //                    };
        //                }
                        
        //                public void remove() {
        //                    throw new UnsupportedOperationException();
        //                }
        //            };
        //        }
                
        //        public int size() {
        //            try {
        //                return getModelEx().size();
        //            }
        //            catch(TemplateModelException e) {
        //                throw new UndeclaredThrowableException(e);
        //            }
        //        }
        //    };
        //}
        
        private ITemplateHashModelEx GetModelEx()
        {
            if (_model is ITemplateHashModelEx)
            {
                return ((ITemplateHashModelEx) _model);
            }
            throw new NotSupportedException(
                    "Operation supported only on TemplateHashModelEx. " + 
                    _model.GetType().FullName + " does not implement it though.");
        }
        
    }
}